#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pyright: reportOperatorIssue=false
"""
Excel数据导入API - 精简版本
保留所有核心功能，移除代码冗余
"""

import os
import time
import re
import csv
import json
import pandas as pd
from datetime import datetime, date
from flask import Blueprint, request, jsonify, current_app, url_for, send_file
from werkzeug.utils import secure_filename

from backend.infrastructure.database import db
from backend.models.student import Student
from backend.models.student_extension import StudentExtension

# ✅修正：完全移除旧配置导入，统一使用新配置系统
# from backend.constants import (
#     EXCEL_FIELD_MAPPING, 
#     INTERVENTION_IMPORT_DEFAULTS, 
#     DATE_FORMATS,
#     DATA_VALIDATION_PATTERNS,
#     NUMERIC_VALIDATION_RANGES
# )

# ✅修正：统一使用新配置管理器
from backend.config.config_manager import ConfigManager

# 初始化配置管理器并获取配置
config_manager = ConfigManager()
EXCEL_FIELD_MAPPING = config_manager.get_excel_field_mapping()
INTERVENTION_IMPORT_DEFAULTS = config_manager.get_intervention_import_defaults()
DATE_FORMATS = config_manager.get_date_formats()
DATA_VALIDATION_PATTERNS = config_manager.get_data_validation_patterns()
NUMERIC_VALIDATION_RANGES = config_manager.get_numeric_validation_ranges()
BOOLEAN_FIELDS_MAPPING = config_manager.get_boolean_fields_mapping()

# ✅新增：恢复必要的模型导入声明
try:
    from backend.services.student_extension_service import ensure_yearly_extension
    EXTENSION_SERVICE_AVAILABLE = True
except ImportError as e:
    EXTENSION_SERVICE_AVAILABLE = False
    print(f"注意：StudentExtensionService导入失败: {e}")

# 临时处理：模型导入
try:
    from backend.models.vision import VisionRecord
    from backend.services.vision_calculation import calculate_vision_metrics
    VISION_MODELS_AVAILABLE = True
except ImportError as e:
    VISION_MODELS_AVAILABLE = False
    print(f"注意：VisionRecord模型导入失败: {e}")

try:
    from backend.models.intervention import InterventionRecord
    INTERVENTION_MODELS_AVAILABLE = True
except ImportError as e:
    INTERVENTION_MODELS_AVAILABLE = False
    print(f"注意：InterventionRecord模型导入失败: {e}")

# 配置常量
ALLOWED_EXTENSIONS = {"xlsx", "csv"}
TEMP_UPLOAD_DIR = os.path.join(os.getcwd(), "temp_uploads")
FAILURE_UPLOAD_DIR = os.path.join(os.getcwd(), "frontend", "static", "uploads")

for dir_path in [TEMP_UPLOAD_DIR, FAILURE_UPLOAD_DIR]:
    if not os.path.exists(dir_path):
        os.makedirs(dir_path)

import_api = Blueprint("import_api", __name__)

# ✅优化：提取常量配置（v3.0）
# 定义需要转换为浮点数的视力相关字段
NUMERIC_VISION_FIELDS = [
    'right_eye_naked', 'left_eye_naked', 'right_eye_corrected', 'left_eye_corrected',
    'right_sphere', 'left_sphere', 'right_cylinder', 'left_cylinder',
    'right_axis', 'left_axis', 'right_dilated_sphere', 'left_dilated_sphere',
    'right_dilated_cylinder', 'left_dilated_cylinder', 'right_dilated_axis', 'left_dilated_axis',
    'right_keratometry_K1', 'left_keratometry_K1', 'right_keratometry_K2', 'left_keratometry_K2',
    'right_axial_length', 'left_axial_length', 'right_anterior_depth', 'left_anterior_depth',
    'right_dilated_vision', 'left_dilated_vision'
]

def parse_date_with_repair(date_str):
    """智能日期解析和修复 - 优化使用配置中的日期格式"""
    if not date_str or pd.isna(date_str):
        return None
    
    # 转换为字符串处理
    date_str = str(date_str).strip()
    
    # 处理特殊的年月格式：2016.5 -> 2016-05-01
    if re.match(r'^\d{4}\.\d{1,2}$', date_str):
        try:
            year, month = date_str.split('.')
            year = int(year)
            month = int(month)
            if 1 <= month <= 12:
                return date(year, month, 1)
        except (ValueError, TypeError):
            pass
    
    # 处理不完整日期格式：201606 -> 2016-06-01
    if re.match(r'^\d{6}$', date_str):
        try:
            year = int(date_str[:4])
            month = int(date_str[4:6])
            if 1 <= month <= 12:
                return date(year, month, 1)
        except (ValueError, TypeError):
            pass
    
    # ✅优化：使用constants.py中的日期格式配置（v3.0）
    for fmt in DATE_FORMATS:
        try:
            parsed_date = datetime.strptime(date_str, fmt).date()
            return parsed_date
        except ValueError:
            continue
    
    print(f"无法解析日期格式: {date_str}")
    return None

def clean_value(value):
    """清理数据值 - 增强日期处理"""
    # 处理pandas的NaN值
    if pd.isna(value):
        return None
    
    # 处理None值
    if value is None:
        return None
    
    # 转换为字符串处理
    str_value = str(value).strip()
    
    # 只清理真正的空值，保留"无"、"否"等有效字符串
    if str_value in ['', 'null', 'NULL', 'None', '—', '-', 'nan', 'NaN']:
        return None
    
    # 保留"无"、"否"、"不详"等有效的业务数据
    return str_value

def convert_boolean_value(value):
    """转换布尔值 - 将Excel中的'1'/'0'转换为True/False"""
    if value is None or pd.isna(value):
        return None
    
    str_value = str(value).strip()
    
    # Excel中常见的表示"是"的值
    if str_value in ['1', '是', 'True', 'true', 'YES', 'yes', 'Y', 'y']:
        return True
    
    # Excel中常见的表示"否"的值  
    if str_value in ['0', '否', 'False', 'false', 'NO', 'no', 'N', 'n', '']:
        return False
    
    # 其他值保持原样
    return value

def process_excel_row(row_data):
    """处理单行Excel数据 - 增强日期处理"""
    processed = {}
    
    # 使用映射表处理数据
    for excel_field, db_field in EXCEL_FIELD_MAPPING.items():
        if excel_field in row_data:
            cleaned_value = clean_value(row_data[excel_field])
            
            # 特殊处理出生日期字段
            if db_field == 'birthday' and cleaned_value:
                parsed_date = parse_date_with_repair(cleaned_value)
                processed[db_field] = parsed_date
            # 新增：特殊处理布尔字段
            elif db_field in BOOLEAN_FIELDS_MAPPING and cleaned_value is not None:
                processed[db_field] = convert_boolean_value(cleaned_value)
            else:
                processed[db_field] = cleaned_value
    
    # 处理矫正方式多选
    correction_methods = []
    for method in ['框架眼镜', '隐形眼镜', '夜戴角膜塑形镜']:
        if row_data.get(method) and clean_value(row_data[method]):
            correction_methods.append(method)
    processed['correction_method'] = ','.join(correction_methods) if correction_methods else None
    
    return processed

def validate_student_identity(existing_student, new_data):
    """验证学生身份信息是否一致"""
    identity_fields = {
        'name': '姓名',
        'gender': '性别', 
        'id_card': '身份证号码'
    }
    
    inconsistent_fields = []
    
    for field, display_name in identity_fields.items():
        existing_value = getattr(existing_student, field, None)
        new_value = new_data.get(field, None)
        
        # 如果两个值都存在且不相等，则不一致
        if existing_value and new_value and existing_value != new_value:
            inconsistent_fields.append(display_name)
    
    return inconsistent_fields

def update_student_blank_fields(existing_student, new_data):
    """只更新学生表中的空白字段，不覆盖已有数据"""
    updated_fields = []
    
    # 定义可更新的学生基本信息字段
    updatable_fields = [
        'school', 'class_name', 'birthday', 'phone', 'id_card',
        'region', 'contact_address', 'parent_name', 'parent_phone'
    ]
    
    for field in updatable_fields:
        existing_value = getattr(existing_student, field, None)
        new_value = new_data.get(field, None)
        
        # 只在现有字段为空且新数据有值时更新
        if not existing_value and new_value:
            setattr(existing_student, field, new_value)
            updated_fields.append(field)
    
    return updated_fields

def update_extension_blank_fields(existing_extension, new_data):
    """只更新扩展表中的空白字段，不覆盖已有数据"""
    updated_fields = []
    
    # 定义可更新的扩展信息字段（排除自动计算字段）
    updatable_fields = [
        'height', 'weight', 'diet_preference', 'exercise_preference',
        'health_education', 'past_history', 'family_history', 
        'premature', 'allergy', 'correction_method'
    ]
    
    for field in updatable_fields:
        existing_value = getattr(existing_extension, field, None)
        new_value = new_data.get(field, None)
        
        # 只在现有字段为空且新数据有值时更新
        if not existing_value and new_value:
            setattr(existing_extension, field, new_value)
            updated_fields.append(field)
    
    return updated_fields

def check_vision_record_duplicate(student_id, measure_date):
    """检查视力记录是否重复（按测量日期）"""
    if not VISION_MODELS_AVAILABLE:
        return False
    
    existing_record = VisionRecord.query.filter_by(
        student_id=student_id,
        measure_date=measure_date
    ).first()
    
    return existing_record is not None

def check_intervention_record_duplicate(student_id, intervention_date):
    """检查干预记录是否重复（按干预日期）"""
    if not INTERVENTION_MODELS_AVAILABLE:
        return False
    
    existing_record = InterventionRecord.query.filter_by(
        student_id=student_id,
        date=intervention_date
    ).first()
    
    return existing_record is not None

def safe_set_field(data_dict, field_name, value, description="字段"):
    """
    ✅ 安全设置字段值（简化重复try-catch，但保持原有逻辑）
    """
    try:
        data_dict[field_name] = value
        return True
    except Exception as e:
        print(f"设置{description} {field_name} 失败: {e}")
        return False

def create_or_update_student(processed_data, data_year):
    """创建或更新学生记录 - 使用扩展服务确保年度记录"""
    education_id = processed_data.get('education_id')
    
    # ❌ 问题1：缺少birthday的类型验证和转换
    birthday = processed_data.get('birthday')
    if birthday and not isinstance(birthday, date):
        birthday = parse_date_with_repair(birthday)
        if not birthday:
            raise ValueError(f"无法解析出生日期: {processed_data.get('birthday')}")
        processed_data['birthday'] = birthday
    
    # 查找现有学生
    existing_student = Student.query.filter_by(education_id=education_id).first()
    
    if existing_student:
        # 验证学生身份信息是否一致
        inconsistent_fields = validate_student_identity(existing_student, processed_data)
        if inconsistent_fields:
            raise ValueError(f"教育ID重复但学生信息不一致：{', '.join(inconsistent_fields)}不符")
        
        # 身份一致，更新空白字段
        updated_student_fields = update_student_blank_fields(existing_student, processed_data)
        if updated_student_fields:
            print(f"✅重复导入测试：学生{existing_student.id}({education_id})更新空白字段 {updated_student_fields}")
        else:
            print(f"✅重复导入测试：学生{existing_student.id}({education_id})无需更新（所有字段已有值）")
        
        student = existing_student
    else:
        # 创建新学生
        student = Student(
            education_id=education_id,
            name=processed_data.get('name'),
            gender=processed_data.get('gender'),
            school=processed_data.get('school'),
            class_name=processed_data.get('class_name'),
            birthday=processed_data.get('birthday'),
            phone=processed_data.get('phone'),
            id_card=processed_data.get('id_card'),
            region=processed_data.get('region'),  # ✅ 修正：添加缺失的字段
            contact_address=processed_data.get('contact_address'),
            parent_name=processed_data.get('parent_name'),
            parent_phone=processed_data.get('parent_phone')
        )
        db.session.add(student)
        db.session.flush()
        print(f"创建新学生记录：{education_id} - {processed_data.get('name')}")
    
    # 处理扩展记录 - 按年份管理
    existing_extension = StudentExtension.query.filter_by(
        student_id=student.id, 
        data_year=data_year
    ).first()
    
    if existing_extension:
        # 同年份数据，只更新空白字段
        updated_extension_fields = update_extension_blank_fields(existing_extension, processed_data)
        if updated_extension_fields:
            print(f"✅重复导入测试：学生{student.id}更新{data_year}年扩展记录空白字段 {updated_extension_fields}")
        else:
            print(f"✅重复导入测试：学生{student.id}的{data_year}年扩展记录无需更新")
        extension = existing_extension
    else:
        # ✅可选：使用扩展服务创建记录（如果需要自动继承功能）
        if EXTENSION_SERVICE_AVAILABLE:
            extension = ensure_yearly_extension(student.id, data_year)
            # 然后更新导入的字段
            for field_name, field_value in processed_data.items():
                if hasattr(extension, field_name) and field_value is not None:
                    setattr(extension, field_name, field_value)
        else:
            # 原有逻辑：直接创建新扩展记录
            extension = StudentExtension(
                student_id=student.id,
                data_year=data_year,
                grade=processed_data.get('grade'),
                age=processed_data.get('age'),
                height=processed_data.get('height'),
                weight=processed_data.get('weight'),
                diet_preference=processed_data.get('diet_preference'),
                exercise_preference=processed_data.get('exercise_preference'),
                health_education=processed_data.get('health_education'),
                past_history=processed_data.get('past_history'),
                family_history=processed_data.get('family_history'),
                premature=processed_data.get('premature'),
                allergy=processed_data.get('allergy'),
                correction_method=processed_data.get('correction_method')
            )
            db.session.add(extension)
        
        print(f"学生{student.id}：创建{data_year}年新扩展记录")
    
    # 解析干预日期
    raw_data = processed_data.get('_raw_data', {})
    intervention_dates = parse_intervention_dates(raw_data)
    
    # 处理视力记录 - ✅ 修正6：改进测量序号的安全设置
    if VISION_MODELS_AVAILABLE:
        baseline_data = {}
        intervention_data = {}
        
        # 分离基线和干预数据
        for excel_field, db_field in EXCEL_FIELD_MAPPING.items():
            if excel_field in raw_data:
                cleaned_value = clean_value(raw_data[excel_field])
                if cleaned_value is not None and db_field.startswith(('right_', 'left_')):
                    if '干预' in excel_field:
                        intervention_data[db_field] = cleaned_value
                    else:
                        baseline_data[db_field] = cleaned_value
        
        baseline_data = convert_vision_data_types(baseline_data)
        intervention_data = convert_vision_data_types(intervention_data)
        
        try:
            created_records = []
            
            # 创建基线候选记录 - 使用工具函数简化
            if baseline_data and intervention_dates:
                baseline_date = intervention_dates[0]['date']
                
                if not check_vision_record_duplicate(student.id, baseline_date):
                    baseline_record_data = {
                        'student_id': student.id,
                        'measure_date': baseline_date,
                        'measure_type': '基线数据',
                        'measurer': '系统导入',
                        'is_baseline': False,
                        'data_year': data_year,
                        **baseline_data
                    }
                    
                    # ✅ 简化：使用工具函数，但逻辑完全相同
                    safe_set_field(baseline_record_data, 'measurement_sequence', 1, "基线测量序号")
                    if student.birthday:
                        safe_set_field(baseline_record_data, 'age_at_measure', 
                                     calculate_age_at_date(student.birthday, baseline_date), "基线测量年龄")
                    
                    baseline_record = VisionRecord(**baseline_record_data)
                    db.session.add(baseline_record)
                    db.session.flush()
                    
                    if 'calculate_vision_metrics' in globals():
                        calculate_vision_metrics(baseline_record)
                    
                    created_records.append(baseline_record)
                    print(f"学生{student.id}：创建基线候选记录，日期：{baseline_date}")
            
            # 创建随访记录 - 使用工具函数简化
            if intervention_data and intervention_dates and len(intervention_dates) > 1:
                followup_date = intervention_dates[-1]['date']
                
                if not check_vision_record_duplicate(student.id, followup_date):
                    followup_record_data = {
                        'student_id': student.id,
                        'measure_date': followup_date,
                        'measure_type': '随访数据',
                        'measurer': '系统导入',
                        'is_baseline': False,
                        'data_year': data_year,
                        **intervention_data
                    }
                    
                    # ✅ 简化：使用工具函数，但逻辑完全相同
                    safe_set_field(followup_record_data, 'measurement_sequence', 2, "随访测量序号")
                    if student.birthday:
                        safe_set_field(followup_record_data, 'age_at_measure',
                                     calculate_age_at_date(student.birthday, followup_date), "随访测量年龄")
                    
                    followup_record = VisionRecord(**followup_record_data)
                    db.session.add(followup_record)
                    db.session.flush()
                    calculate_vision_metrics(followup_record)
                    created_records.append(followup_record)
                    print(f"学生{student.id}：创建随访记录，日期：{followup_date}")
            
            # 重新计算测量次序和基线标记
            if created_records:
                recalculate_vision_sequence_and_baseline(student.id)
                
        except Exception as e:
            print(f"学生{student.id}：视力记录创建失败 - {e}")
            import traceback
            traceback.print_exc()
    
    # ✅ 简化：干预记录处理也使用工具函数
    if INTERVENTION_MODELS_AVAILABLE and intervention_dates:
        try:
            from datetime import time
            
            existing_intervention_count = InterventionRecord.query.filter_by(
                student_id=student.id
            ).count()
            
            # ✅ 修复：批量导入时正确计算累计值
            # 先统计该学生已有的干预记录数量
            from sqlalchemy import func
            existing_counts = db.session.query(
                InterventionRecord.intervention_type,
                func.count(InterventionRecord.id).label('count')
            ).filter_by(student_id=student.id).group_by(InterventionRecord.intervention_type).all()
            
            # 构建现有累计值字典
            existing_cumulative = {}
            for intervention_type, count in existing_counts:
                if intervention_type == "刮痧":
                    existing_cumulative['guasha_count'] = count
                elif intervention_type == "艾灸":
                    existing_cumulative['aigiu_count'] = count
                elif intervention_type == "耳穴压丸":
                    existing_cumulative['erxue_yawan_count'] = count
                elif intervention_type == "中药熏蒸":
                    existing_cumulative['zhongyao_xunzheng_count'] = count
                elif intervention_type == "热灸训练":
                    existing_cumulative['rejiu_training_count'] = count
                elif intervention_type == "热磁脉冲":
                    existing_cumulative['reci_pulse_count'] = count
                elif intervention_type == "拔罐":
                    existing_cumulative['baoguan_count'] = count
            
            # 初始化累计值
            current_cumulative = {
                'guasha_count': existing_cumulative.get('guasha_count', 0),
                'aigiu_count': existing_cumulative.get('aigiu_count', 0),
                'erxue_yawan_count': existing_cumulative.get('erxue_yawan_count', 0),
                'zhongyao_xunzheng_count': existing_cumulative.get('zhongyao_xunzheng_count', 0),
                'rejiu_training_count': existing_cumulative.get('rejiu_training_count', 0),
                'reci_pulse_count': existing_cumulative.get('reci_pulse_count', 0),
                'baoguan_count': existing_cumulative.get('baoguan_count', 0)
            }
            
            intervention_type = INTERVENTION_IMPORT_DEFAULTS.get('intervention_type', '耳穴压丸')
            
            for idx, intervention_info in enumerate(intervention_dates, existing_intervention_count + 1):
                if not check_intervention_record_duplicate(student.id, intervention_info['date']):
                    default_time = time(9, 0, 0)
                    
                    intervention_record_data = {
                        'student_id': student.id,
                        'intervention_date': intervention_info['date'],  # ✅修正：使用正确的字段名
                    }
                    
                    # ✅ 简化：使用工具函数设置所有字段（逻辑完全相同）
                    safe_set_field(intervention_record_data, 'intervention_type', 
                                 intervention_type, "干预类型")
                    safe_set_field(intervention_record_data, 'operation_time', time(10, 0, 0), "操作时间")  # 修改：改为10:00
                    safe_set_field(intervention_record_data, 'operator', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('operator', '曲线社区医生'), "操作员")
                    safe_set_field(intervention_record_data, 'duration_minutes', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('duration_minutes', 5), "持续时间")  # 新增
                    safe_set_field(intervention_record_data, 'operation_tools', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('operation_tools'), "操作工具")  # 新增
                    safe_set_field(intervention_record_data, 'consumed_materials', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('consumed_materials'), "消耗材料")  # 新增
                    safe_set_field(intervention_record_data, 'operation_sites', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('operation_sites'), "操作部位")  # 新增
                    safe_set_field(intervention_record_data, 'acupoints', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('acupoints'), "穴位选择")  # 新增
                    safe_set_field(intervention_record_data, 'press_methods', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('press_methods'), "贴压方式")  # 新增
                    safe_set_field(intervention_record_data, 'details', 
                                 f'Excel导入：第{idx}次干预（全局序号）', "详情")
                    safe_set_field(intervention_record_data, 'press_strength', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('press_strength', '中度'), "按压强度")
                    safe_set_field(intervention_record_data, 'press_frequency', 
                                 INTERVENTION_IMPORT_DEFAULTS.get('press_frequency', 30), "按压频率")  # 新增
                    safe_set_field(intervention_record_data, 'data_year', data_year, "数据年份")
                    safe_set_field(intervention_record_data, 'is_imported', True, "导入标记")
                    safe_set_field(intervention_record_data, 'import_source', f"Excel导入_{data_year}", "导入来源")
                    safe_set_field(intervention_record_data, 'session_number', idx - existing_intervention_count, "会话编号")
                    safe_set_field(intervention_record_data, 'global_sequence', idx, "全局序号")
                    
                    # ✅ 修复：设置正确的累计值
                    if intervention_type == "刮痧":
                        current_cumulative['guasha_count'] += 1
                        safe_set_field(intervention_record_data, 'guasha_count', current_cumulative['guasha_count'], "刮痧累计次数")
                    elif intervention_type == "艾灸":
                        current_cumulative['aigiu_count'] += 1
                        safe_set_field(intervention_record_data, 'aigiu_count', current_cumulative['aigiu_count'], "艾灸累计次数")
                    elif intervention_type == "耳穴压丸":
                        current_cumulative['erxue_yawan_count'] += 1
                        safe_set_field(intervention_record_data, 'erxue_yawan_count', current_cumulative['erxue_yawan_count'], "耳穴压丸累计次数")
                    elif intervention_type == "中药熏蒸":
                        current_cumulative['zhongyao_xunzheng_count'] += 1
                        safe_set_field(intervention_record_data, 'zhongyao_xunzheng_count', current_cumulative['zhongyao_xunzheng_count'], "中药熏蒸累计次数")
                    elif intervention_type == "热灸训练":
                        current_cumulative['rejiu_training_count'] += 1
                        safe_set_field(intervention_record_data, 'rejiu_training_count', current_cumulative['rejiu_training_count'], "热灸训练累计次数")
                    elif intervention_type == "热磁脉冲":
                        current_cumulative['reci_pulse_count'] += 1
                        safe_set_field(intervention_record_data, 'reci_pulse_count', current_cumulative['reci_pulse_count'], "热磁脉冲累计次数")
                    elif intervention_type == "拔罐":
                        current_cumulative['baoguan_count'] += 1
                        safe_set_field(intervention_record_data, 'baoguan_count', current_cumulative['baoguan_count'], "拔罐累计次数")

                    intervention_record = InterventionRecord(**intervention_record_data)
                    
                    # ✅ 修复：不调用auto_fill_fields()，因为我们已经手动设置了累计值
                    # 只调用其他自动填充逻辑
                    try:
                        # 只设置数据年份和数据来源，不更新累计统计
                        if intervention_record.intervention_date is not None:
                            if isinstance(intervention_record.intervention_date, str):
                                try:
                                    from datetime import datetime
                                    date_obj = datetime.strptime(intervention_record.intervention_date, '%Y-%m-%d').date()
                                    intervention_record.intervention_date = date_obj
                                except ValueError:
                                    pass
                            
                            if hasattr(intervention_record.intervention_date, 'year') and not isinstance(intervention_record.intervention_date, str):
                                intervention_record.data_year = str(intervention_record.intervention_date.year)
                        
                        if intervention_record.upload_source is None or not intervention_record.upload_source:
                            intervention_record.upload_source = 'Excel导入'
                    except Exception as e:
                        print(f"学生{student.id}：自动填充字段失败 - {e}")
                    
                    db.session.add(intervention_record)
                    print(f"学生{student.id}：创建第{idx}次干预记录（{data_year}年），日期：{intervention_info['date']}，累计值：{current_cumulative.get('erxue_yawan_count', 0)}")
                else:
                    print(f"学生{student.id}：干预日期{intervention_info['date']}已存在记录，跳过创建")
            
            db.session.flush()
            
        except Exception as e:
            print(f"学生{student.id}：干预记录创建失败 - {e}")
            import traceback
            traceback.print_exc()
    
    return student

def generate_error_log_file(error_logs, original_filename, data_year):
    """生成错误日志文件"""
    if not error_logs:
        return None
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    error_filename = f"导入错误记录_{original_filename}_{data_year}_{timestamp}.csv"
    error_filepath = os.path.join(FAILURE_UPLOAD_DIR, error_filename)
    
    try:
        with open(error_filepath, 'w', newline='', encoding='utf-8-sig') as csvfile:
            fieldnames = ['序号', '行号', '教育ID号', '错误描述', '原始数据']
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            
            writer.writeheader()
            for idx, error in enumerate(error_logs, 1):
                writer.writerow({
                    '序号': idx,
                    '行号': error.get('row', '未知'),
                    '教育ID号': error.get('education_id', '未知'),
                    '错误描述': error.get('error', ''),
                    '原始数据': json.dumps(error.get('raw_data', {}), ensure_ascii=False)
                })
        return error_filename
        
    except Exception as e:
        current_app.logger.error(f"生成错误日志文件失败: {str(e)}")
        return None

@import_api.route("/api/students/import", methods=["POST"])
def import_students():
    """导入学生数据 - 修正验证和安全性问题"""
    temp_filepath = None
    
    try:
        # 基础验证
        if 'file' not in request.files:
            return jsonify({"error": "未找到上传文件"}), 400

        file = request.files['file']
        if file.filename == '':
            return jsonify({"error": "未选择文件"}), 400

        filename = secure_filename(file.filename or '')
        original_filename = file.filename
        data_year = request.form.get("data_year", "").strip()
        
        # 验证年份
        if not data_year or not data_year.isdigit() or not (2000 <= int(data_year) <= 2030):
            return jsonify({"error": "请选择有效的数据年份(2000-2030)"}), 400
        
        # 验证文件名包含年份
        year_variations = [data_year, data_year[2:], data_year[-2:]]
        if not any(year in (original_filename or '') for year in year_variations):
            return jsonify({
                "error": f"文件名中未包含所选年份({data_year})信息",
                "details": f"请确认文件名和年份选择是否匹配。文件名: {original_filename}, 选择年份: {data_year}",
                "validation_type": "year_mismatch"
            }), 400
        
        # 验证文件扩展名
        ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else ''
        if ext not in ALLOWED_EXTENSIONS:
            return jsonify({"error": f"不支持的文件格式，仅支持: {', '.join(ALLOWED_EXTENSIONS)}"}), 400

        # 保存临时文件
        temp_filepath = os.path.join(TEMP_UPLOAD_DIR, f"upload_{int(time.time())}.{ext}")
        file.save(temp_filepath)

        # 验证文件大小
        if os.path.getsize(temp_filepath) > 50 * 1024 * 1024:
            return jsonify({"error": "文件大小超过50MB限制"}), 400

        # 读取Excel数据
        try:
            if ext == 'xlsx':
                df = pd.read_excel(temp_filepath, dtype=str)
            else:
                df = pd.read_csv(temp_filepath, dtype=str, encoding='utf-8')
        except Exception as e:
            return jsonify({"error": f"文件读取失败: {str(e)}"}), 400

        if df.empty:
            return jsonify({"error": "Excel文件为空"}), 400

        # 清理数据
        df = df.fillna('')
        df.columns = df.columns.str.strip()
        
        # 验证必要列
        required_columns = ['教育ID号', '姓名', '性别', '学校', '班级']
        missing_columns = [col for col in required_columns if col not in df.columns]
        
        if missing_columns:
            return jsonify({
                "error": f"Excel文件缺少必要列: {', '.join(missing_columns)}",
                "available_columns": list(df.columns),
                "required_columns": required_columns
            }), 400

        current_app.logger.info(f"开始处理文件: {original_filename}, 年份: {data_year}, 行数: {len(df)}")

        # 处理数据
        success_count = 0
        error_count = 0
        error_logs = []
        update_count = 0  # 有实际更新的记录计数
        duplicate_count = 0  # 重复但无更新的记录计数
        
        # 处理每行数据
        for row_index, (index, row) in enumerate(df.iterrows(), 1):
            try:
                row_data = row.to_dict()
                processed_data = process_excel_row(row_data)
                processed_data['_raw_data'] = row_data
                
                # ✅ 修正5：增强的字段验证（包含身份证、手机号、数值范围验证）
                education_id = processed_data.get('education_id')
                name = processed_data.get('name')
                gender = processed_data.get('gender')
                school = processed_data.get('school')
                class_name = processed_data.get('class_name')
                birthday = processed_data.get('birthday')
                id_card = processed_data.get('id_card')
                phone = processed_data.get('phone')
                parent_phone = processed_data.get('parent_phone')
                age = processed_data.get('age')
                height = processed_data.get('height')
                weight = processed_data.get('weight')
                
                # 检查必填字段
                validation_errors = []
                if not education_id:
                    validation_errors.append("教育ID号不能为空")
                elif not re.match(DATA_VALIDATION_PATTERNS['education_id'], education_id):
                    validation_errors.append("教育ID号格式不正确，应为7-20位数字")
                    
                if not name:
                    validation_errors.append("姓名不能为空")
                if not gender:
                    validation_errors.append("性别不能为空")
                elif gender not in ['男', '女']:
                    validation_errors.append("性别值不正确，应为：男、女")
                if not school:
                    validation_errors.append("学校不能为空")
                if not class_name:
                    validation_errors.append("班级不能为空")
                
                # ✅ 修正：增强的出生日期验证
                if birthday and not isinstance(birthday, date):
                    validation_errors.append("出生日期格式不正确，应为YYYY-MM-DD或YYYY.MM格式")
                
                # ✅ 新增：身份证号验证
                if id_card:
                    field_errors = validate_field_value('id_card', id_card)
                    if field_errors:
                        validation_errors.extend(field_errors)
                
                # ✅ 新增：手机号验证
                if phone:
                    field_errors = validate_field_value('phone', phone)
                    if field_errors:
                        validation_errors.extend(field_errors)
                
                if parent_phone:
                    field_errors = validate_field_value('parent_phone', parent_phone)
                    if field_errors:
                        validation_errors.extend(field_errors)
                
                # ✅ 新增：数值范围验证
                for field_name, field_value in [('age', age), ('height', height), ('weight', weight)]:
                    if field_value:
                        field_errors = validate_field_value(field_name, field_value)
                        if field_errors:
                            validation_errors.extend(field_errors)
                
                # ✅ 新增：视力数值验证
                for field_name, field_value in processed_data.items():
                    if field_value and field_name in NUMERIC_VISION_FIELDS:
                        field_errors = validate_field_value(field_name, field_value)
                        if field_errors:
                            validation_errors.extend(field_errors)
                
                if validation_errors:
                    row_number = row_index + 1  # 因为enumerate从1开始，所以+1就是实际行号
                    error_logs.append({
                        'row': row_number,
                        'error': '; '.join(validation_errors),
                        'education_id': education_id or 'N/A',
                        'raw_data': row_data
                    })
                    error_count += 1
                    print(f"第{row_number}行验证失败: {'; '.join(validation_errors)}")
                    continue
                
                # 新增：身份验证前置检查
                existing_student = Student.query.filter_by(education_id=education_id).first()
                if existing_student:
                    inconsistent_fields = validate_student_identity(existing_student, processed_data)
                    if inconsistent_fields:
                        # 记录身份不一致错误，跳过此条记录
                        row_number = row_index + 1
                        error_logs.append({
                            'row': row_number,
                            'error': f"❌重复导入测试：教育ID重复但学生信息不一致：{', '.join(inconsistent_fields)}不符",
                            'education_id': education_id,
                            'raw_data': row_data
                        })
                        error_count += 1
                        print(f"❌重复导入测试：第{row_number}行身份验证失败: 教育ID重复但{', '.join(inconsistent_fields)}不一致")
                        continue
                
                # 使用独立事务处理每条记录
                try:
                    # 检查是否为重复记录的逻辑已内置到create_or_update_student中
                    existing_extension = StudentExtension.query.join(Student).filter(
                        Student.education_id == education_id,
                        StudentExtension.data_year == data_year
                    ).first()
                    
                    if existing_extension:
                        # 这是一个重复记录，需要检查是否有实际更新
                        student_before = Student.query.filter_by(education_id=education_id).first()
                        extension_before = existing_extension
                        
                        # 记录更新前的字段状态
                        student_fields_before = {field: getattr(student_before, field, None) for field in 
                                               ['school', 'class_name', 'birthday', 'phone', 'id_card', 'region', 'contact_address', 'parent_name', 'parent_phone']}
                        extension_fields_before = {field: getattr(extension_before, field, None) for field in 
                                                 ['height', 'weight', 'diet_preference', 'exercise_preference', 'health_education', 'past_history', 'family_history', 'premature', 'allergy', 'correction_method']}
                        
                        create_or_update_student(processed_data, data_year)
                        
                        # 检查是否有实际更新
                        has_update = False
                        
                        # 检查学生表字段是否有更新
                        for field, old_value in student_fields_before.items():
                            new_value = getattr(student_before, field, None)
                            if old_value != new_value:
                                has_update = True
                                break
                        
                        # 检查扩展表字段是否有更新
                        if not has_update:
                            for field, old_value in extension_fields_before.items():
                                new_value = getattr(extension_before, field, None)
                                if old_value != new_value:
                                    has_update = True
                                    break
                        
                        if has_update:
                            update_count += 1
                            print(f"✅重复导入测试：第{index + 2}行更新成功: {education_id} - {name}")
                        else:
                            duplicate_count += 1
                            print(f"✅重复导入测试：第{index + 2}行重复无变化: {education_id} - {name}")
                    else:
                        # 这是一个新增操作
                        create_or_update_student(processed_data, data_year)
                        success_count += 1
                        print(f"✅重复导入测试：第{index + 2}行新增成功: {education_id} - {name}")
                    
                    # 每50条提交一次
                    if (success_count + update_count + duplicate_count) % 50 == 0:
                        db.session.commit()
                        current_app.logger.info(f"已处理 {index + 1} 行，新增 {success_count} 条，更新 {update_count} 条，重复 {duplicate_count} 条")
                        
                except Exception as record_error:
                    # 单条记录失败时，回滚当前记录但继续处理下一条
                    db.session.rollback()
                    error_detail = format_import_error(row, record_error, index + 2)
                    error_logs.append(error_detail)
                    error_count += 1
                    print(f"❌重复导入测试：第{index + 2}行处理失败: {error_detail['error']}")
                    continue
                
            except Exception as row_error:
                try:
                    db.session.rollback()
                except:
                    pass
                error_detail = format_import_error(row, row_error, index + 2)
                error_logs.append(error_detail)
                error_count += 1
                continue
        
        # 最终提交
        db.session.commit()
        print(f"✅重复导入测试完成：新增{success_count}条，更新{update_count}条，重复无变化{duplicate_count}条，错误{error_count}条")

        # 生成错误日志文件
        error_log_filename = None
        error_log_download_url = None
        if error_logs:
            error_log_filename = generate_error_log_file(error_logs, original_filename, data_year)
            if error_log_filename:
                error_log_download_url = url_for('import_api.download_error_log', 
                                                  filename=error_log_filename, 
                                                  _external=False)

        # 构建响应 - 修复重复导入统计显示
        response = {
            "status": "success",
            "message": "数据导入完成",
            "total_rows": len(df),
            "success_count": success_count,
            "update_count": update_count,
            "error_count": error_count,
            "duplicate_education_ids": update_count + duplicate_count,  # 总重复记录数
            "duplicate_no_change": duplicate_count,  # 新增：重复但无变化的记录数
            "success_rate": round(((success_count + update_count + duplicate_count) / len(df)) * 100, 1) if len(df) > 0 else 0,
            "data_year": data_year,
            "original_filename": original_filename,
            "has_errors": error_count > 0
        }
        
        # 修复：恢复我删除的错误日志字段处理
        if error_log_filename:
            response["error_log_filename"] = error_log_filename
            response["error_log_download_url"] = error_log_download_url
        
        if error_logs:
            response["error_logs"] = error_logs[:50]
            response["total_error_count"] = len(error_logs)

        return jsonify(response), 200

    except Exception as e:
        try:
            db.session.rollback()
        except:
            pass
        
        current_app.logger.error(f"导入异常: {str(e)}")
        return jsonify({
            "error": f"导入失败: {str(e)}",
            "error_type": "system_error",
            "suggestion": "请检查文件格式和数据完整性，特别是日期字段格式"
        }), 500
    
    finally:
        if temp_filepath and os.path.exists(temp_filepath):
            try:
                os.remove(temp_filepath)
            except Exception as e:
                current_app.logger.warning(f"清理临时文件失败: {e}")

@import_api.route("/api/students/import/download_error_log/<filename>", methods=["GET"])
def download_error_log(filename):
    """下载错误日志文件"""
    try:
        if not re.match(r'^导入错误记录_.*\.csv$', filename):
            return jsonify({"error": "无效的文件名"}), 400
        
        file_path = os.path.join(FAILURE_UPLOAD_DIR, filename)
        
        if not os.path.exists(file_path):
            return jsonify({"error": "错误日志文件不存在"}), 404
        
        # 检查文件年龄
        file_age = time.time() - os.path.getctime(file_path)
        if file_age > 7 * 24 * 3600:  # 7天
            os.remove(file_path)
            return jsonify({"error": "错误日志文件已过期"}), 404
        
        return send_file(
            file_path,
            as_attachment=True,
            download_name=filename,
            mimetype='text/csv'
        )
        
    except Exception as e:
        current_app.logger.error(f"下载错误日志失败: {str(e)}")
        return jsonify({"error": "下载失败"}), 500

def convert_vision_data_types(data):
    """转换视力数据为正确的数值类型 - 优化使用配置"""
    converted = {}
    
    for field, value in data.items():
        if field in NUMERIC_VISION_FIELDS and value is not None:
            try:
                # 转换为浮点数
                converted[field] = float(value)
            except (ValueError, TypeError):
                print(f"数值转换失败: {field} = {value}")
                converted[field] = None
        else:
            converted[field] = value
    
    return converted

def parse_intervention_dates(row_data):
    """解析Excel中的干预日期字段 - 优化日期格式处理"""
    intervention_dates = []
    
    # 只查找"第X次干预"格式的字段，避免错误解析视力数据
    for field_name, field_value in row_data.items():
        # 精确匹配"第X次干预"格式，排除其他包含"干预"的字段
        if re.match(r'^第\d+次干预$', field_name.strip()) and field_value:
            cleaned_value = clean_value(field_value)
            if cleaned_value:
                try:
                    parsed_date = None
                    
                    # 如果pandas已经解析为datetime对象
                    if hasattr(field_value, 'date'):
                        parsed_date = field_value.date()
                    else:
                        # 尝试字符串解析
                        date_str = str(cleaned_value).strip()
                        
                        # 处理带时间戳的日期格式
                        if ' ' in date_str:
                            date_str = date_str.split(' ')[0]  # 只取日期部分
                        
                        # ✅优化：使用配置中的日期格式（v3.0）
                        for fmt in DATE_FORMATS:
                            try:
                                parsed_date = datetime.strptime(date_str, fmt).date()
                                break
                            except ValueError:
                                continue
                    
                    if parsed_date:
                        intervention_dates.append({
                            'field_name': field_name,
                            'date': parsed_date,
                            'raw_value': str(field_value)
                        })
                        print(f"成功解析干预日期: {field_name} = {parsed_date}")
                    else:
                        print(f"无法解析干预日期: {field_name} = {field_value}")
                        
                except Exception as e:
                    print(f"解析干预日期异常 {field_name}: {field_value} - {e}")
    
    # 按日期排序
    intervention_dates.sort(key=lambda x: x['date'])
    print(f"共解析到{len(intervention_dates)}个干预日期")
    return intervention_dates

def recalculate_vision_sequence_and_baseline(student_id):
    """重新计算学生所有视力记录的测量次序并判定基线"""
    if not VISION_MODELS_AVAILABLE:
        return
    
    try:
        # 查询该学生所有视力记录，按测量日期排序
        all_records = VisionRecord.query.filter_by(
            student_id=student_id
        ).order_by(VisionRecord.measure_date).all()
        
        if not all_records:
            return
        
        # ✅ 修正6：安全设置测量次序，使用try-catch
        try:
            for idx, record in enumerate(all_records, 1):
                record.measurement_sequence = idx
        except Exception:
            pass  # 如果measurement_sequence字段不存在，忽略设置
        
        # 清除所有基线标记
        for record in all_records:
            record.is_baseline = False
        
        # 将时间最早的记录标记为基线
        earliest_record = all_records[0]
        earliest_record.is_baseline = True
        
        # 重新计算基线对比字段和视力等级
        baseline_record = earliest_record
        for record in all_records:
            if record.id != baseline_record.id:
                # 使用统一的基线对比计算服务
                from backend.services.vision_calculation import calculate_baseline_comparisons
                calculate_baseline_comparisons(record)
            
            # 确保视力等级计算完整性
            if hasattr(record, 'vision_level') and not record.vision_level:
                if 'calculate_vision_metrics' in globals():
                    calculate_vision_metrics(record)
        
        print(f"学生{student_id}：重新计算{len(all_records)}条视力记录的次序，基线记录日期：{earliest_record.measure_date}")
        
    except Exception as e:
        print(f"学生{student_id}：重新计算视力记录次序失败 - {e}")

# 已删除重复的基线变化计算函数，统一使用vision_calculation.py中的calculate_baseline_comparisons

def calculate_age_at_date(birthday, measure_date):
    """计算指定日期时的年龄"""
    if not birthday or not measure_date:
        return None
    
    try:
        age = measure_date.year - birthday.year
        
        # 考虑月日调整
        if measure_date.month < birthday.month or \
           (measure_date.month == birthday.month and measure_date.day < birthday.day):
            age -= 1
        
        return age
    except Exception as e:
        print(f"计算年龄失败: {e}")
        return None

def validate_field_value(field_name, field_value, field_type='text'):
    """
    ✅ 必须补充：字段值验证函数（解决函数未定义错误）
    """
    if not field_value:
        return []  # ✅ 修正：返回空列表，表示无验证错误，允许空值通过
    
    validation_errors = []
    
    # 身份证号验证
    if field_name in ['id_card'] and not re.match(DATA_VALIDATION_PATTERNS['id_card'], str(field_value)):
        validation_errors.append("身份证号码格式不正确，应为18位数字+校验位(最后一位可为X)")
    
    # 手机号验证
    elif field_name in ['phone', 'parent_phone'] and not re.match(DATA_VALIDATION_PATTERNS['phone'], str(field_value)):
        validation_errors.append("手机号码格式不正确，应为11位1开头的号码")
    
    # 数值范围验证
    elif field_name in ['age', 'height', 'weight']:
        try:
            if field_name in NUMERIC_VALIDATION_RANGES:
                range_config = NUMERIC_VALIDATION_RANGES[field_name]
                if range_config['type'] == 'integer':
                    value = int(field_value)
                else:
                    value = float(field_value)
                
                if not (range_config['min'] <= value <= range_config['max']):
                    validation_errors.append(f"{range_config['name']}应在{range_config['min']}-{range_config['max']}范围内")
        except (ValueError, TypeError):
            validation_errors.append(f"{field_name}格式不正确，应为有效数字")
    
    # 视力数值验证
    elif field_name.endswith(('_naked', '_corrected', '_vision')):
        try:
            value = float(field_value)
            vision_range = NUMERIC_VALIDATION_RANGES['vision']
            if not (vision_range['min'] <= value <= vision_range['max']):
                validation_errors.append(f"视力值应在{vision_range['min']}-{vision_range['max']}范围内")
        except (ValueError, TypeError):
            validation_errors.append("视力值格式不正确，应为有效数字")
    
    # 屈光度验证
    elif field_name.endswith(('_sphere', '_cylinder')):
        try:
            value = float(field_value)
            if '_sphere' in field_name:
                range_config = NUMERIC_VALIDATION_RANGES['sphere']
            else:
                range_config = NUMERIC_VALIDATION_RANGES['cylinder']
            
            if not (range_config['min'] <= value <= range_config['max']):
                validation_errors.append(f"{range_config['name']}应在{range_config['min']}-{range_config['max']}范围内")
        except (ValueError, TypeError):
            validation_errors.append("屈光度格式不正确，应为有效数字")
    
    # 轴位验证
    elif field_name.endswith('_axis'):
        try:
            value = float(field_value)
            axis_range = NUMERIC_VALIDATION_RANGES['axis']
            if not (axis_range['min'] <= value <= axis_range['max']):
                validation_errors.append(f"轴位应在{axis_range['min']}-{axis_range['max']}度范围内")
        except (ValueError, TypeError):
            validation_errors.append("轴位格式不正确，应为有效数字")
    
    return validation_errors

def analyze_error_type(exception, student_info):
    """分析异常类型并返回中文错误描述 - 增强日期错误处理"""
    error_str = str(exception).lower()
    original_error = str(exception)  # ✅ 保留原始异常信息
    
    # 日期格式错误 - 优先处理
    if 'incorrect date value' in error_str or 'invalid date' in error_str:
        birthday_value = student_info.get('birthday', 'N/A')
        return f"出生日期格式错误：'{birthday_value}'，请使用YYYY-MM-DD格式（如：2016-05-01），或确保年月格式完整"
    
    # 数据库约束错误
    if 'duplicate entry' in error_str or 'unique constraint' in error_str:
        if 'unique_student_baseline' in error_str:
            return f"学生 '{student_info['name']}' (教育ID: {student_info['education_id']}) 已存在基线数据，不能重复录入"
        elif 'education_id' in error_str:
            return f"教育ID号 '{student_info['education_id']}' 已存在，不能重复录入"
        else:
            return f"数据库约束错误：{original_error}"  # ✅ 显示原始错误信息
    
    # 外键约束错误
    elif 'foreign key constraint' in error_str or 'cannot add or update' in error_str:
        return f"数据关联错误：{original_error}"  # ✅ 显示原始错误信息
    
    # 数据类型错误 - 新增数据格式非法处理
    elif 'invalid literal' in error_str or 'could not convert' in error_str or 'cannot be null' in error_str:
        if 'float' in error_str:
            return f"数值格式错误：{original_error}。请检查视力值、球镜、柱镜、轴位等字段格式是否为有效数字"
        elif 'int' in error_str:
            return f"整数格式错误：{original_error}。请检查年龄、身高、体重等字段格式是否为有效整数"
        elif 'date' in error_str:
            return f"日期格式错误：{original_error}。请检查日期字段格式是否正确"
        else:
            return f"数据格式错误：{original_error}。请检查字段格式是否正确"
    
    # 数值范围错误 - 新增
    elif 'out of range' in error_str or 'value too large' in error_str:
        return f"数值超出允许范围：{original_error}。请检查数值字段是否在合理范围内"
    
    # 字符串长度错误 - 新增
    elif 'data too long' in error_str or 'string too long' in error_str:
        return f"字符串内容过长：{original_error}。请检查文本字段长度是否超出限制"
    
    # 数据库连接或权限错误
    elif 'connection' in error_str:
        return f"数据库连接错误：{original_error}。请检查数据库服务和网络连接"
    
    # ✅ 关键修改：显示完整原始异常信息，而不是模糊的"未知错误"
    return f"系统错误：{original_error}。请联系系统管理员并提供此错误信息"

def format_import_error(row, exception, excel_row_number):
    """格式化导入错误信息为用户友好的中文描述 - 增强错误记录"""
    try:
        # 提取学生基本信息
        if hasattr(row, 'to_dict'):
            row_dict = row.to_dict()
        else:
            row_dict = row
            
        student_info = {
            'excel_row': excel_row_number,
            'education_id': row_dict.get('教育ID号', '') or row_dict.get('education_id', ''),
            'name': row_dict.get('姓名', '') or row_dict.get('name', ''),
            'gender': row_dict.get('性别', '') or row_dict.get('gender', ''),
            'school': row_dict.get('学校', '') or row_dict.get('school', ''),
            'birthday': row_dict.get('出生日期', '') or row_dict.get('birthday', ''),
        }
        
        # ✅ 增强：记录完整异常信息到控制台，便于调试
        print(f"❌ 第{excel_row_number}行导入失败：{str(exception)}")
        
        # 分析错误类型并生成中文描述
        error_message = analyze_error_type(exception, student_info)
        
        # 返回错误记录对象
        return {
            'row': excel_row_number,
            'education_id': student_info['education_id'],
            'error': error_message,
            'raw_data': row_dict
        }
        
    except Exception as format_error:
        # ✅ 增强：格式化失败时也要记录原始异常
        print(f"❌ 第{excel_row_number}行错误格式化失败：{str(format_error)}")
        print(f"❌ 原始异常：{str(exception)}")
        
        # 如果格式化也失败，返回原始异常信息
        return {
            'row': excel_row_number,
            'education_id': 'N/A',
            'error': f"数据处理失败：{str(exception)[:300]}",  # ✅ 增加异常信息长度
            'raw_data': {}
        }